/**
 * @Description HomeController.java
 * @author xu_cc [18724000100@163.com]
 * @date 创建时间：2017年9月21日 下午4:07:42
 */
package com.solution.pc.home.controller;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.solution.admin.auth.entity.UserEntity;
import com.solution.admin.auth.security.UsernamePasswordToken;
import com.solution.admin.auth.service.UserService;
import com.solution.admin.customer.service.CustomerLoginHistoryService;
import com.solution.admin.home.service.RedisService;
import com.solution.admin.home.service.SequenceService;
import com.solution.admin.point.constants.PointConstants.PointOperateFlag;
import com.solution.admin.point.constants.PointConstants.PointOperateType;
import com.solution.admin.point.entity.PointLogEntity;
import com.solution.admin.point.entity.SignPointSettingsEntity;
import com.solution.admin.point.service.PointLogService;
import com.solution.admin.point.service.PointService;
import com.solution.admin.point.service.SignPointSettingsService;
import com.solution.admin.product.service.ProductCategoryService;
import com.solution.admin.settings.entity.KeyMapEntity;
import com.solution.admin.settings.service.KeyMapService;
import com.solution.common.config.PublicConfigUtil;
import com.solution.common.constants.PublicStatus;
import com.solution.common.constants.PublicStatus.SysCode;
import com.solution.common.constants.PublicStatus.USER_APPROVE_STATUS;
import com.solution.common.controller.BaseController;
import com.solution.common.entity.BaseReturn;
import com.solution.common.utils.RandomUtils;
import com.solution.common.utils.UUIDUtil;
import com.solution.common.utils.ip.IPUtils;
import com.solution.common.utils.sms.AliyunSmsUtils;
import com.solution.common.utils.string.StringUtil;
import com.solution.pc.home.constants.HomeConstants.SmsTemplateType;
import com.solution.pc.home.constants.HomeConstants.UserDataKey;
import com.solution.wx.my.constants.MyConstants;

/**
 * 商城首页
 * 
 * @author xu_cc
 * @date 创建时间：2017年9月21日 下午4:13:16
 */
@RequestMapping("/home")
@Controller
public class HomeController extends BaseController {

	private Logger logger = LoggerFactory.getLogger(HomeController.class);

	@Autowired
	UserService userService;

	@Autowired
	ProductCategoryService productCategoryService;

	@Autowired
	PointService pointService;

	@Autowired
	PointLogService pointLogService;

	@Autowired
	SignPointSettingsService signPointSettingsService;

	@Autowired
	CustomerLoginHistoryService customerLoginHistoryService;

	@Autowired
	SequenceService sequenceService;

	@Autowired
	RedisService redisService;
	
	@Autowired
	KeyMapService keyMapService;

	@RequestMapping("/getSeq")
	@ResponseBody
	public BaseReturn getSeq(HttpServletRequest request, String seqName) {
		BaseReturn result = new BaseReturn();
		try {
			if (StringUtil.isEmpty(seqName)) {
				seqName = UUIDUtil.generateAllString(3);
			}
			System.out.println("序列名：" + seqName);
			long seqNo = sequenceService.getSequenceNumber(seqName);
			System.out.println("序列号：" + seqNo);
			result.setCode(SysCode.SUCCESS);
			result.setMsg("序列名：" + seqName + "序列号：" + seqNo);
		} catch (Exception e) {
			result.setCode(SysCode.ERROR);
			result.setMsg("签到异常，请重试！");
			e.printStackTrace();
		}
		return result;
	}

	/**
	 * PC端登录页面
	 * 
	 * @param request
	 * @param model
	 * @return String
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年9月21日 下午4:42:08
	 */
	@RequestMapping("/loginPage")
	public String toLoginPage(HttpServletRequest request, Model model) {
		return "pc/login/login";
	}

	/**
	 * 转到找回密码页面
	 * 
	 * @param request
	 * @param model
	 * @return String
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年9月24日 下午4:29:08
	 */
	@RequestMapping("/toFindPwdPage")
	public String toFindPwdPage(HttpServletRequest request, Model model) {
		model.addAttribute("step", 1);// 第一步
		return "pc/login/findPwd";
	}

	/**
	 * 找回密码
	 * 
	 * @param request
	 * @param userCode
	 * @param step
	 * @param model
	 * @param userId
	 * @param password
	 * @param passwordSalt
	 * @return String
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年9月24日 下午5:20:14
	 */
	@RequestMapping("/doFindPwd")
	public String doFindPwd(HttpServletRequest request, String userCode, String step, Model model, String userId, String password, String passwordSalt) {
		try {
			if (StringUtil.isEmpty(step)) {
				model.addAttribute("error", "请输入用户名！");// 第一步
				return "";
			}
			if ("1".equals(step)) {
				Map<String, Object> params = new Hashtable<String, Object>();
				params.put("loginName", userCode);
				UserEntity user = userService.getUserByName(params);
				if (null == user) {
					model.addAttribute("step", 1);
					model.addAttribute("error", "无法匹配到该用户！");// 第一步
				} else {
					model.addAttribute("step", 2);
					model.addAttribute("user", user);
					model.addAttribute("id", user.getId());
					model.addAttribute("passwordSalt", user.getPasswordSalt());
					model.addAttribute("userCode", user.getUserCode());
					model.addAttribute("userName", user.getUserName());
					model.addAttribute("mobile", user.getMobile());
					model.addAttribute("userNameShow", cutString(user.getUserName(), 1, 1));
					// 手机号中间4位换成*（18712345678 --》 187****5678）
					String mobile = user.getMobile().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
					model.addAttribute("mobileShow", mobile);// cutString(user.getMobile(),
					                                         // 3, 4)
				}
			} else if ("2".equals(step)) {
				model.addAttribute("id", userId);
				model.addAttribute("userCode", userCode);
				model.addAttribute("passwordSalt", passwordSalt);
				model.addAttribute("step", 3);
			} else if ("3".equals(step)) {
				Long id = Long.parseLong(userId);
				int rows = userService.resetUserPwdByMobile(id, userCode, password, passwordSalt);
				if (rows > 0) {
					model.addAttribute("error", "重置密码成功！");
					model.addAttribute("step", 4);
				} else {
					model.addAttribute("error", "重置密码异常！");
					model.addAttribute("step", 3);
				}
			} else {
				return "pc/login/login";
			}
			return "pc/login/findPwd";
		} catch (Exception e) {
			e.printStackTrace();
			model.addAttribute("step", step);// 第一步
			model.addAttribute("error", "找回密码异常！");// 第一步
		}
		return "pc/login/findPwd";
	}

	/**
	 * 发送手机验证码
	 * 
	 * @param request
	 * @return
	 * @author: solin
	 * @date: 2017年11月16日 上午11:28:41
	 */
	@RequestMapping("/sendMobileCode")
	@ResponseBody
	public Map<String, Object> sendVerifyCode(HttpServletRequest request, String mobile) {
		Map<String, Object> resultMap = new HashMap<String, Object>();
		try {
			// redis中的验证码KEY
			String verifyCodeKey = MyConstants.REGISTER_MOBILE_KEY.concat(mobile);
			// 发送短信
//			String templateId = "SMS_126866486";
			String verifyCode = RandomUtils.getRandNum(6);
			// 保存到redis
			redisService.save(verifyCodeKey, verifyCode, (30 * 60));
			System.out.println("============>>>短信验证码:" + verifyCode);
			String params = "{\"code\":\"" + verifyCode + "\"}";
			AliyunSmsUtils.sendSms(SmsTemplateType.SMS_FIND_PWD.getTemplateId(), mobile, params);
			resultMap.put("code", 1);
			resultMap.put("msg", "短信验证码发送成功！");
		} catch (Exception e) { 
			e.printStackTrace();
			resultMap.put("code", 0);
			resultMap.put("msg", "短信验证码发送失败！");
		}
		return resultMap;
	}
	
	/**
	 * 页面显示截取
	 * 
	 * @param orgStr
	 * @param start
	 * @param end
	 * @return String
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年9月24日 下午5:02:03
	 */
	private static String cutString(String orgStr, int start, int end) {
		try {
			if (StringUtil.isEmpty(orgStr)) {
				return "*";
			}
			if (orgStr.length() > (start + end)) {
				return orgStr.substring(0, start) + fullStar(orgStr.length(), (start + end)) + orgStr.substring(orgStr.length() - end);
			} else if (orgStr.length() > start) {
				return orgStr.substring(0, start) + fullStar(orgStr.length(), (start + end));
			} else {
				return orgStr + "*";
			}
		} catch (Exception e) {
			return orgStr;
		}
	}

	/**
	 * 补齐*
	 * 
	 * @param length
	 * @param i
	 * @return String
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年9月24日 下午5:07:23
	 */
	private static String fullStar(int length, int i) {
		int count = length - i;
		String starStr = "";
		for (int j = 0; j < count; j++) {
			starStr += "*";
		}
		return starStr;
	}

	/**
	 * 验证用户是否登录
	 * 
	 * @param request
	 * @return BaseReturn
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年12月26日 下午8:28:08
	 */
	@RequestMapping("/isLogin")
	@ResponseBody
	public BaseReturn isAuthenticated(HttpServletRequest request) {
		BaseReturn result = new BaseReturn();
		try {
			if(getSubject().isAuthenticated()){
				result.setCode(SysCode.SUCCESS);
			}else{
				result.setCode(SysCode.FAILED);
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(SysCode.ERROR);
		}
		return result;
	}

	/**
	 * 客户执行签到
	 * 
	 * @Title: doSign
	 * @Description:(描述)
	 * @param request
	 * @param customerId
	 * @return BaseReturn
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年10月25日 上午9:58:23
	 */
	@RequestMapping("/doSign")
	@ResponseBody
	public BaseReturn doSign(HttpServletRequest request) {
		BaseReturn result = new BaseReturn();
		try {
			Long customerId = getCustomerId();

			if (null == customerId) {
				result.setCode(SysCode.FAILED);
				result.setMsg("签到失败，未知的客户信息！");
			} else {
				//签到控制,是否允许签到 1 允许,其他 禁止
				List<KeyMapEntity> signInControlList = keyMapService.listKeyMap("signInControl");
				if (null != signInControlList && signInControlList.size() != 0) {
					KeyMapEntity signInControl = signInControlList.get(0);
					if (!"1".equals(signInControl.getKeyValue())) {
						result.setCode(SysCode.FAILED);
						result.setMsg("今日无法签到！");
						return result;
					}
				}
				// 是否已经签到
				Map<String, Object> param = new HashMap<String, Object>();
				param.put("customerId", customerId);
				param.put("operateType", PointOperateType.OPT_SIGN.getCode());
				param.put("today", 1);// today只要有值就行，不限制
				List<PointLogEntity> signLogList = pointLogService.listPointLog(param);
				if (null != signLogList && signLogList.size() > 0) {
					result.setCode(SysCode.FAILED);
					result.setMsg("今日已签到成功！");
				} else {
					// 默认签到所得积分是 0
					BigDecimal signPoint = BigDecimal.ZERO;
					String pattern = "yyyy-MM-dd";
					String currentDateStr = DateFormatUtils.format(new Date(), pattern);
					// 查看今天是否有签到积分设置信息
					Map<String, Object> paramMap = new HashMap<String, Object>();
					paramMap.put("startTime", currentDateStr);
					paramMap.put("endTime", currentDateStr);
					// 查看是否有时间冲突的记录
					List<SignPointSettingsEntity> signPointSettingsList = signPointSettingsService.listSignPointSettings(paramMap);
					if (null != signPointSettingsList && signPointSettingsList.size() > 0) {
						// 获取设置的积分
						signPoint = signPointSettingsList.get(0).getSignPoint();
					} else {
						// 取不到签到积分规则，那就取默认签到赠送积分
						String signPointStr = PublicConfigUtil.readConfig("sign.default.point");
						if (StringUtil.isNotNull(signPointStr)) {
							signPoint = new BigDecimal(signPointStr);
						}
					}
					// 执行签到操作
					int rows = pointService.doOperatePointCommon(customerId, PointOperateFlag.FLAG_ADD.getId(), PointOperateType.OPT_SIGN.getCode(),
					        signPoint, "签到", null, null, getUserCode(), false);
					if (rows > 0) {
						result.setCode(SysCode.SUCCESS);
						result.setMsg("签到成功！");
					} else {
						result.setCode(SysCode.FAILED);
						result.setMsg("签到失败，请重试！");
					}
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(SysCode.ERROR);
			result.setMsg("签到出现异常，请重试！");
		}
		return result;
	}

	/**
	 * 登录
	 * 
	 * @return String
	 * @author xu_cc
	 * @throws Exception
	 *             exception
	 * @Date 创建时间：2017年9月21日 下午4:55:20
	 */
	@RequestMapping("/login")
	@ResponseBody
	public BaseReturn login(HttpServletRequest request, Model model, String userCode, String password) {
		// , String mobile, String mobileCode, String type
		BaseReturn result = new BaseReturn();
		try {
			// 从redis验证该用户是否在锁定状态
			String lockUserKey = "LOCKUSER_" + userCode;
			Long secondsLong = redisService.getExpire(lockUserKey);
			int secondsInt = secondsLong.intValue();
			// 当 key 不存在时，返回 -2 。
			// 当 key 存在但没有设置剩余生存时间时，返回 -1 。
			// 否则，以秒为单位，返回 key 的剩余生存时间
			if (secondsInt > 0) {
				// 说明该用户真的是在锁定状态，直接返回
				int minutes = (secondsInt / 60);
				int seconds = (secondsInt % 60);
				String timeStr = ((minutes > 0) ? minutes + "分" : "") + seconds + "秒";
				result.setCode(SysCode.FAILED);
				result.setMsg("该账户正在锁定状态，请 " + timeStr + " 后重试！");
				return result;
			}
			String loginCountKey = UserDataKey.LOGIN_COUNT + IPUtils.getIntenetIP(request);
			int count = (null == redisService.get(loginCountKey)) ? 0 : Integer.parseInt(redisService.get(loginCountKey));
			String userCountKey = UserDataKey.LOGIN_COUNT + IPUtils.getIntenetIP(request);
			int userCount = (null == redisService.get(userCountKey)) ? 0 : Integer.parseInt(redisService.get(userCountKey));
			int surplus = (userCount >= 10) ? 1 : 10 - userCount;
			// 超过10次，账户锁定，锁定时间可配置（用户锁定信息应该是放在redis缓存中）
			if (count >= 10 || userCount >= 10) {
				int minutes = (null != PublicConfigUtil.readConfig("LOCK_USER_TIME")) ? Integer.parseInt(PublicConfigUtil
				        .readConfig("LOCK_USER_TIME")) : 10;
				// 将锁定用户存在redis中，加上前缀：LOCKUSER_
				redisService.save(lockUserKey, userCode, (minutes * 60));
				// 登录失败次数重新计数
				redisService.del(loginCountKey);
				redisService.del(userCountKey);
				// 设置锁定用户在redis中
				// 获取锁定配置时间（分钟）
				// String minutes =
				// PublicConfigUtil.readConfig("lockUserTime");
				// 优先从配置中获取用户锁定时间，若获取不到，则默认10分钟
				result.setCode(SysCode.FAILED);
				result.setMsg("失败次数过多，该账户已锁定！请于 " + minutes + " 分钟后重试！");
				return result;
			}
			// 先期校验完成，执行登录操作
			try {
				// 首先验证用户的状态 根据用户名查找用户
				UserEntity user = userService.getUserByCode(userCode);
				if(null == user) {
					Map<String, Object> param = new HashMap<String, Object>();
					param.put("mobile", userCode);
					List<UserEntity> userList = userService.getUserList(param);
					user = (null != userList && userList.size() > 0) ? userList.get(0) : null;
				}
				if(null != user) {
					if(USER_APPROVE_STATUS.REJECT.getId().equals(user.getStatus())) {
						result.setCode(SysCode.FAILED);
						result.setMsg("您的帐号审核失败，您可以联系系统人员或者重新发起申请！");
						return result;
					}
				}
				
				Subject currentUser = SecurityUtils.getSubject();
				UsernamePasswordToken token = new UsernamePasswordToken();
				token.setUsername(userCode);
				token.setPassword(password.toCharArray());
				token.setLoginTerminal(PublicStatus.LOGIN_TERMINAL_TYPE.PC.getCode());
				currentUser.login(token);
				// 如果登录成功，则清空登录统计次数
				// 删除图片验证码、短信验证码、登录错误次数、用户登录次数在redis的记录
				String authKey = UserDataKey.CODE_AUTH_CODE + IPUtils.getIntenetIP(request);
				String mobileKey = UserDataKey.CODE_MOBILE_CODE + IPUtils.getIntenetIP(request);
				redisService.del(authKey);
				redisService.del(mobileKey);
				redisService.del(loginCountKey);
				redisService.del(userCountKey);
				
				//签到控制,是否允许签到 1 允许,其他 禁止
				List<KeyMapEntity> signInControlList = keyMapService.listKeyMap("signInControl");
				if (null != signInControlList && signInControlList.size() != 0) {
					KeyMapEntity signInControl = signInControlList.get(0);
					if ("1".equals(signInControl.getKeyValue())) {
						request.setAttribute("signInControl", signInControl.getKeyValue());
					} else {
						request.setAttribute("signInControl", "0");
					}
				}
				// 跳转首页
				result.setCode(SysCode.SUCCESS);
				result.setMsg("用户名校验成功！");
				// 记录登录历史
				try {
					customerLoginHistoryService.saveCustomerLoginHistory(userCode);
				} catch (Exception e) {
					logger.error("记录客户【{}】登录历史失败，{}", userCode, e);
				}
				return result;
			} catch (Exception e) {
				e.printStackTrace();
				count++;
				// request.getSession().setAttribute("COUNT", count);
				redisService.save(loginCountKey, count + "", (30 * 60));
				userCount++;
				redisService.save(userCountKey, userCount + "", (30 * 60));
				// request.getSession().setAttribute(userCode, userCount);
				result.setCode(SysCode.FAILED);
				result.setMsg("用户名密码验证不正确，您还有" + surplus + "次机会！");
				return result;
			}
		} catch (Exception e) {
			e.printStackTrace();
			result.setCode(SysCode.ERROR);
			result.setMsg("用户名密码验证异常！");
			return result;
		}
	}

	/**
	 * 判断用户是否已经登录
	 * 
	 * @param request
	 * @return
	 * @author llp
	 */
	@RequestMapping("/checkLogin")
	@ResponseBody
	public Map<String, String> checkLogin(HttpServletRequest request) {
		Map<String, String> resultMap = new HashMap<String, String>();
		Subject subject = getSubject();
		resultMap.put(PublicStatus.RESULT_CODE, subject.isAuthenticated() ? "1" : "0");
		resultMap.put(PublicStatus.RESULT_MSG, subject.isAuthenticated() ? "用户已登录" : "用户未登录");
		return resultMap;
	}
	
	/**
	 * 检查当日是否允许签到
	 * @param request
	 * @return
	 * @author xkl
	 * @date 2018年3月21日 下午5:56:28
	 */
	@RequestMapping("/checkAllowSign")
	@ResponseBody
	public Map<String, Object> checkAllowSign(HttpServletRequest request){
		Map<String, Object> resultMap = new HashMap<String, Object>();
		//签到控制,是否允许签到 1 允许,其他 禁止
		try {
			List<KeyMapEntity> signInControlList = keyMapService.listKeyMap("signInControl");
			if (null != signInControlList && signInControlList.size() != 0) {
				KeyMapEntity signInControl = signInControlList.get(0);
				resultMap.put("allowSign", signInControl.getKeyValue());
			}
		} catch (Exception e) {
			e.printStackTrace();
			resultMap.put("allowSign", 0);
		}
		return resultMap;
	}
}
